package com.fadadianqi.logistics.admin.printer;

import com.fadadianqi.commons.ConfigHelper;
import com.fadadianqi.commons.VelocityWrapper;
import com.fadadianqi.logistics.customer.model.Customer;
import com.fadadianqi.logistics.customer.model.Town;
import com.fadadianqi.logistics.customer.model.Village;
import com.fadadianqi.logistics.customer.service.CustomerService;
import com.fadadianqi.goods.model.Brand;
import com.fadadianqi.goods.model.Category;
import com.fadadianqi.goods.model.Goods;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.logistics.sell.model.Bill;
import com.fadadianqi.logistics.sell.model.Item;
import com.fadadianqi.logistics.sell.service.BillService;
import com.yeqiangwei.commons.util.BeanUtils;
import com.yeqiangwei.commons.util.DateTimeUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.print.Paper;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

@Service
public class BillPrinter {

    private static final Logger log = Logger.getLogger(BillPrinter.class);

    public void doPrint(String billId) throws PrinterException {
        int offsetX = ConfigHelper.getInt("vm.printer.offsetX", 10);
        int offsetY = ConfigHelper.getInt("vm.printer.offsetY", 10);
        int width = ConfigHelper.getInt("vm.printer.width", 585);
        int height = ConfigHelper.getInt("vm.printer.height", 800);
        Paper p = new Paper();
        p.setSize(width, height); // 纸张大小
        p.setImageableArea(offsetX, offsetY, width, height);
        PrintService printService = new PrintService(getContent(billId), p);
        printService.doPrint();
    }

    private void contextWapper(VelocityContext context, String billId) {
        // 这个是用来判断是否打印商品单价
        context.put("printer_goods_price", ConfigHelper.getBoolean("printer.goods.price"));
        context.put("title", ConfigHelper.getString("printer.title"));
        context.put("address", ConfigHelper.getString("printer.address"));
        context.put("tel", ConfigHelper.getString("printer.tel"));
        Bill bill = billService.getById(billId);
        if (bill == null) {
            log.error("bill is null " + billId);
            return;
        }
        String fmt = DateTimeUtils.FMT_YYYY_MM_DD_HH_MM_SS;
        String datetime = DateTimeUtils.format(bill.getAddTime().getTime(), fmt);
        context.put("datetime", datetime);
        context.put("ident", bill.getId());
        context.put("price", bill.getPayables());
        context.put("memo", bill.getMemo());
        context.put("bill", bill);
        Customer customer = customerService.getById(bill.getCustomerId());
        context.put("customer", customer);
        if (customer != null) {
            Town town = customerService.getTownById(customer.getTownId());
            Village village = customerService.getVillageById(customer.getVillageId());
            context.put("town", town);
            context.put("village", village);
        }
        List<com.fadadianqi.logistics.sell.model.Goods> items = billService.findGoodsByBillId(billId);
        List<GoodsVO> voList = new ArrayList<GoodsVO>();
        if (items == null) {
            return;
        }
        for (com.fadadianqi.logistics.sell.model.Goods goods : items) {
            String gid = goods.getGoodsId();
            String bid = goods.getBillId();
            Item item = billService.getItemByGoodsIdAndBillId(gid, bid);
            if (item != null && item.getIsReturn()) {
                continue;
            }
            GoodsVO vo = new GoodsVO();
            BeanUtils.copyProperties(vo, goods);
            vo.setGoods(goodsService.getGoodsById(gid));
            vo.setBrand(goodsService.getBrandById(goods.getBrandId()));
            vo.setCategory(goodsService.getCategoryById(goods.getCategoryId()));
            voList.add(vo);
        }
        context.put("items", voList);
    }

    private String getContent(String billId) {
        String baseDir = System.getProperty("base.dir", "..");
        String path = baseDir + "printer" + File.separator;

        log.debug("billId: " + billId);
        log.debug("path: " + path);
        log.debug("file.resource.loader.path: " + ConfigHelper.getString("vm.printer.template.path", path));
        log.debug("vm.printer.template.name: " + ConfigHelper.getString("vm.printer.template.name"));

        VelocityEngine ve = VelocityWrapper.getVelocityInstance();
        ve.setProperty("file.resource.loader.path", ConfigHelper.getString("vm.printer.template.path", path));
        Template t = VelocityWrapper.getTemplate(ve, ConfigHelper.getString("vm.printer.template.name"));
        VelocityContext context = new VelocityContext();
        contextWapper(context, billId);
        StringWriter writer = new StringWriter();
        try {
            t.merge(context, writer);
        } catch (ResourceNotFoundException e) {
            log.error(e.toString());
        } catch (ParseErrorException e) {
            log.error(e.toString());
        } catch (MethodInvocationException e) {
            log.error(e.toString());
        } catch (IOException e) {
            log.error(e.toString());
        }
        return writer.toString();
    }

    @Autowired
    private BillService billService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private GoodsService goodsService;

    public static class GoodsVO extends com.fadadianqi.logistics.sell.model.Goods {

        /**
         *
         */
        private static final long serialVersionUID = 8606897702761288666L;

        private Goods goods;
        private Brand brand;
        private Category category;

        public Goods getGoods() {
            return goods;
        }

        public void setGoods(Goods goods) {
            this.goods = goods;
        }

        public Brand getBrand() {
            return brand;
        }

        public void setBrand(Brand brand) {
            this.brand = brand;
        }

        public Category getCategory() {
            return category;
        }

        public void setCategory(Category category) {
            this.category = category;
        }
    }
}
